<script setup lang="ts">

import {useDouBaoVoiceStore} from "@/store/modules/doubaoVoice.ts";
import {ElNotification} from "element-plus";

defineOptions({
  name: 'VoicePage',
})

const props = defineProps<{
  content?: string
  title?: string
}>()

const douBaoVoiceStore =  useDouBaoVoiceStore()

const voiceModel = ref({
  content: props.content ?? '',
  model: 'doubao',
  format: 'wav', // 输出格式 wav/mp3
  voiceType: 'BV701_streaming', // 音色
  volume: 1.0, // 音量
  speed: 1.0, // 语速
  pitch: 1.0, // 语调
  dialog: false,
  loading: false,
})

const voiceDownloadUrl = ref('')

const voiceAudioShow = ref(false)

const audioRef = ref<HTMLAudioElement | null>(null)
const audioLoaded = ref(false)
const audioLoading = ref(false)
const audioLoadProgress = ref(0)

// 音频开始加载时触发
function onAudioLoadStart() {
  audioLoading.value = true
  audioLoadProgress.value = 0
}

// 音频加载进度更新时触发
function onAudioProgress() {
  if (audioRef.value && audioRef.value.buffered.length > 0) {
    const bufferedEnd = audioRef.value.buffered.end(audioRef.value.buffered.length - 1)
    const duration = audioRef.value.duration
    if (duration > 0) {
      audioLoadProgress.value = (bufferedEnd / duration) * 100
    }
  }
}

// 音频数据加载完成时触发
function onAudioLoaded() {
  audioLoading.value = false
  audioLoaded.value = true
  audioLoadProgress.value = 100
}

// 音频可以播放时触发
function onAudioCanPlay() {
  console.log('音频可以播放')
  audioRef.value?.play()
}

// 监听 voiceDownloadUrl 变化，重置加载状态
watch(() => voiceDownloadUrl.value, () => {
  audioLoaded.value = false
})


async function generateVoice(trial: boolean) {
  voiceModel.value.loading = true
  const param = {
    text: trial ? voiceModel.value.content.substring(0, voiceModel.value.content.length > 50 ? 50 : voiceModel.value.content.length)
      : voiceModel.value.content, // 试听仅支持50字
    format: voiceModel.value.format,
    voice_type: voiceModel.value.voiceType,
    sample_rate: 24000,
    volume: voiceModel.value.volume,
    speed: voiceModel.value.speed,
    pitch: voiceModel.value.pitch,
    enable_subtitle: 1
  }

  try {
    const response = await douBaoVoiceStore.submitTask(param)
    if (response) {
      console.log(response)
      const taskId = response.data.task_id
      if (taskId) {
        let downloadUrl = ''
        while (!downloadUrl) {
          // 等待5秒再查询任务状态
          await new Promise(resolve => setTimeout(resolve, 5000))
          const queryResponse = await douBaoVoiceStore.queryTask(taskId)
          console.log(queryResponse)
          if (queryResponse.data.task_status === 1) {
            downloadUrl = queryResponse.data.audio_url
          }
        }
        voiceDownloadUrl.value = downloadUrl
        if (!trial) {
          ElNotification({
            title: '操作成功',
            message: '配音生成成功...',
            type: 'success',
          })
        }
        voiceAudioShow.value = true
      }
    }
  } catch (error) {
    console.error('生成配音失败:', error)
    ElNotification({
      title: '操作失败',
      message: '生成配音时发生错误',
      type: 'error',
    })
  } finally {
    voiceModel.value.loading = false
  }
}

async function downloadVoice() {
  if (voiceDownloadUrl.value) {
    try {
      // 获取音频文件的Blob数据
      const response = await fetch(voiceDownloadUrl.value);
      const blob = await response.blob();

      // 创建下载链接
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;

      // 设置正确的文件名
      link.download = props.title
        ? `${props.title}.${voiceModel.value.format}`
        : `配音.${voiceModel.value.format}`;

      // 触发下载
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

      // 释放URL对象
      window.URL.revokeObjectURL(url);
    } catch (error) {
      console.error('下载失败:', error);
      ElNotification({
        title: '下载失败',
        message: '音频文件下载时发生错误',
        type: 'error',
      });
    }
  }
}

</script>

<template>
  <div v-loading="voiceModel.loading" element-loading-text="配音生成中...">
    <el-container>
      <el-main>
        <el-input

          type="textarea"
          v-model="voiceModel.content"
          :rows="20"
          placeholder="请输入需要配音的文本内容..."
        />
        <el-divider v-if="voiceAudioShow" />
        <div v-show="voiceAudioShow">
          <!-- 添加加载进度条 -->
          <el-progress
            v-if="audioLoading && !audioLoaded"
            :percentage="audioLoadProgress"
            :show-text="true"
          />
          <audio
            v-show="audioLoaded"
            ref="audioRef"
            controls
            preload="auto"
            :src="voiceDownloadUrl"
            @loadstart="onAudioLoadStart"
            @progress="onAudioProgress"
            @canplay="onAudioCanPlay"
            @loadeddata="onAudioLoaded"
          ></audio>
        </div>
      </el-main>
      <el-aside width="400px">
        <br>
        <el-form :model="voiceModel" label-width="80px">

          <el-form-item label="语音模型">
            <el-select v-model="voiceModel.model" placeholder="请选择语音模型">
              <el-option label="豆包语音" value="doubao" />
            </el-select>
          </el-form-item>

          <el-form-item label="输出格式">
            <el-select v-model="voiceModel.format" placeholder="请选择输出格式">
              <el-option label="WAV" value="wav" />
              <el-option label="MP3" value="mp3" />
            </el-select>
          </el-form-item>

          <el-form-item label="音色选择">
            <el-select v-model="voiceModel.voiceType" placeholder="请选择音色">
              <el-option label="擎苍" value="BV701_streaming" />
              <el-option label="阳光青年" value="BV123_streaming" />
              <el-option label="反卷青年" value="BV120_streaming" />
              <el-option label="通用赘婿" value="BV119_streaming" />
              <el-option label="古风少御" value="BV115_streaming" />
              <el-option label="霸气青叔" value="BV107_streaming" />
              <el-option label="质朴青年" value="BV100_streaming" />
              <el-option label="温柔淑女" value="BV104_streaming" />
              <el-option label="开朗青年" value="BV004_streaming" />
              <el-option label="甜宠少御" value="BV113_streaming" />
              <el-option label="儒雅青年" value="BV102_streaming" />
            </el-select>
          </el-form-item>

          <el-form-item label="音量">
            <el-slider
              v-model="voiceModel.volume"
              :min="0.1"
              :max="3"
              :step="0.1"
              show-input
            />
          </el-form-item>

          <el-form-item label="语速">
            <el-slider
              v-model="voiceModel.speed"
              :min="0.2"
              :max="3"
              :step="0.1"
              show-input
            />
          </el-form-item>

          <el-form-item label="语调">
            <el-slider
              v-model="voiceModel.pitch"
              :min="0.1"
              :max="3"
              :step="0.1"
              show-input
            />
          </el-form-item>
        </el-form>
      </el-aside>
    </el-container>
    <FaPageMain>
      <el-button type="info" @click="generateVoice(true)">试听</el-button>
      <el-button type="primary" @click="generateVoice(false)">生成配音</el-button>
      <el-button type="success" @click="downloadVoice">下载配音</el-button>
      <el-button @click="voiceModel.dialog = false">取消</el-button>
    </FaPageMain>
  </div>
</template>
